package com.zilu.digitaltwin.common.manager;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.zilu.digitaltwin.common.util.HttpClientUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.fluent.Content;
import org.apache.http.client.fluent.Request;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.*;
import java.util.Map;

import static com.sun.org.apache.xml.internal.serialize.OutputFormat.Defaults.Encoding;

/**
 * @author :caijianbao
 * @date : 2023/1/2 22:28
 */
@Slf4j
@Component
public class HttpClientManager {


    public static String sendGet(String uri, String headerName, String headerValue)
            throws IOException {
        Content content = Request.Get(uri).socketTimeout(30000).connectTimeout(30000).setHeader(headerName, headerValue)
                .execute().returnContent();
        return content.asString();
    }

    public static String sendPost(String url, String body, String contentType, String headerName, String headerValue)
            throws IOException {
        Content content = Request.Post(url).socketTimeout(30000).connectTimeout(30000)
                .setHeader(headerName, headerValue)
                .bodyString(body, ContentType.create(contentType)).execute().returnContent();
        return content.asString();
    }

    public static String sendGet(String uri, Map<String, String> headerMap) throws IOException {
        Request request = Request.Get(uri).socketTimeout(30000).connectTimeout(30000);
        for (Map.Entry<String, String> entry : headerMap.entrySet()) {
            request.setHeader(entry.getKey(), entry.getValue());
        }
        Content content = request.execute().returnContent();
        //返回会有中文乱码，手动转换为utf-8
        return new String(content.asBytes(), "UTF-8");
    }


    /**
     * 忽略SSL证书get请求
     *
     * @param url
     * @param params
     * @param headers
     * @return
     * @throws Exception
     */
    public static String sendGet(String url, Map<String, Object> params, Map<String, Object> headers) throws Exception {
        CloseableHttpClient httpClient = HttpClientUtils.createHttpsClient();
        HttpGet httpGet = new HttpGet();
        //构造get请求的url
        String apiUrl = buildGetParam(url, params);
        httpGet.setURI(URI.create(apiUrl));
        buildHeaderValue(httpGet, headers);
        return sendRequest(httpClient, httpGet, apiUrl);
    }


    /**
     * 忽略SSL证书post请求  params和requestBody都是一样的,可以只传一样
     *
     * @param url
     * @param params
     * @param requestBody
     * @param headers
     * @return
     * @throws CloseableHttpClient
     */
    public static String sendPost(String url, Map<String, Object> params, JSONObject requestBody, Map<String, Object> headers) throws Exception {
        CloseableHttpClient httpClient = HttpClientUtils.createHttpsClient();
        HttpPost httpPost = new HttpPost();
        httpPost.setURI(URI.create(url));
        //均建清求信息
        StringEntity entity = new StringEntity(buildPostBody(params, requestBody), Encoding);
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        buildHeaderValue(httpPost, headers);
        return sendRequest(httpClient, httpPost, url);
    }

    /**
     * 发送请求返回byte[]类型二进制数据
     * @param url
     * @param requestBody
     * @param headers
     * @return
     * @throws Exception
     */
    public static byte[] sendPostByte(String url, JSONObject requestBody, Map<String, Object> headers) throws Exception {
        CloseableHttpClient httpClient = HttpClientUtils.createHttpsClient();
        HttpPost httpPost = new HttpPost();
        httpPost.setURI(URI.create(url));
        //均建清求信息
        StringEntity entity = new StringEntity(requestBody.toJSONString(), Encoding);
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        buildHeaderValue(httpPost, headers);
        return sendRequestByte(httpClient, httpPost, url);
    }


    /**
     * 发送请求返回byte[]类型数据
     *
     * @param httpClient
     * @param requestBase
     * @param url
     * @return
     * @throws Exception
     */
    public static byte[] sendRequestByte(CloseableHttpClient httpClient, HttpRequestBase requestBase, String url) throws Exception {
        CloseableHttpResponse response = null;
//        StringBuilder result = new StringBuilder();
        try {
            response = httpClient.execute(requestBase);
            HttpEntity entity = response.getEntity();
            byte[] responseByteArray = EntityUtils.toByteArray(entity);
            return responseByteArray;
        } catch (IOException e) {
            log.error("调用接口异常：", e);
            throw new Exception("调用接口异常：" + e.getMessage() + "，请求串一＞" + url);
        } finally {
            if (null != httpClient) {
                httpClient.close();
            }
            if (response != null) {
                EntityUtils.consume(response.getEntity());
                response.close();
            }
        }
    }


    /**
     * 发送请求
     *
     * @param httpClient
     * @param requestBase
     * @param url
     * @return
     * @throws Exception
     */
    public static String sendRequest(CloseableHttpClient httpClient, HttpRequestBase requestBase, String url) throws Exception {
        CloseableHttpResponse response = null;
        StringBuilder result = new StringBuilder();
        try {
            response = httpClient.execute(requestBase);
            HttpEntity entity = response.getEntity();
            BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
            String str;
            while ((str = reader.readLine()) != null) {
                result.append(str).append("\n");
            }
            EntityUtils.consume(entity);
        } catch (IOException e) {
            log.error("调用接口异常：", e);
            throw new Exception("调用接口异常：" + e.getMessage() + "，请求串一＞" + url);
        } finally {
            if (null != httpClient) {
                httpClient.close();
            }
            if (response != null) {
                EntityUtils.consume(response.getEntity());
                response.close();
            }
        }
        return result.toString();

    }

    /**
     * 构建请求头
     *
     * @param requestBase
     * @param headerMap
     */
    private static void buildHeaderValue(HttpRequestBase requestBase, Map<String, Object> headerMap) {
        if (MapUtils.isNotEmpty(headerMap)) {
            for (Map.Entry<String, Object> entry : headerMap.entrySet()) {
                requestBase.setHeader(entry.getKey(), String.valueOf(entry.getValue()));
            }
        }
    }

    /**
     * 构建get请求的参数
     *
     * @param url
     * @param paramMap
     * @return
     */
    public static String buildGetParam(String url, Map<String, Object> paramMap) {
        if (MapUtils.isNotEmpty(paramMap)) {
            List<NameValuePair> paramList = Lists.newArrayListWithCapacity(paramMap.size());
            for (String key : paramMap.keySet()) {
                paramList.add(new BasicNameValuePair(key, String.valueOf(paramMap.get(key))));
            }
            //拼接参数
            url += "?" + URLEncodedUtils.format(paramList, Consts.UTF_8);
        }
        return url;
    }

    /**
     * 获取post请求的参数
     *
     * @param paramMap
     * @param requestBody
     * @return
     */
    public static String buildPostBody(Map<String, Object> paramMap, JSONObject requestBody) {
        if (requestBody != null) {
            return JSONArray.toJSONString(requestBody);
        } else {
            JSONObject bodyJson = new JSONObject();
            for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                bodyJson.put(entry.getKey(), entry.getValue());
            }
            return JSONArray.toJSONString(bodyJson);
        }
    }

}
